﻿Option Strict On
Option Explicit On
Option Infer On

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Xml.Linq
Imports System.Xml.XPath
Imports GenDotNet.Task.Common
Imports GenDotNet.Model.Common
Imports GenDotNet.Wrapper.Common
Imports <xmlns:orm="http://kadgen.com/KADORM.xsd">
Imports <xmlns:s="http://kadgen.com/Select.xsd">

''' <summary>
''' Base class for generation
''' </summary>
''' <remarks>
''' This interface needs to be refactored for other template types. This might
''' mean overloads, renaming the parameters, or possibly an "args" style interface
''' </remarks>
Public MustInherit Class GenerationBase
   Implements IGenerator

   Protected MustOverride Function GetOutput( _
            ByVal name As String, _
            ByVal rootData As IRootData, _
            ByVal assemblyName As String, _
            ByVal templateName As String, _
            ByRef fileName As String) _
            As String

   Private Function SetXmlDocument( _
               ByVal category As String, _
               ByVal inputXml As XDocument, _
               ByRef hash As Int32) _
               As XElement _
               Implements IGenerator.SetXmlDocument
      ' NOTE: In the following, the comparison is case sensitive to ensure
      '       correct casing
      If inputXml IsNot Nothing Then
         If category = GeneratorCategory.Object Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     GenInputMetadata.RootData.LoadData(inputXml), hash)
         ElseIf category = GeneratorCategory.CreateStoredProc Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     SpInputMetadata.RootData.LoadData(category, inputXml, hash), hash)
         ElseIf category = GeneratorCategory.UpdateStoredProc Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     SpInputMetadata.RootData.LoadData(category, inputXml, hash), hash)
         ElseIf category = GeneratorCategory.DeleteStoredProc Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     SpInputMetadata.RootData.LoadData(category, inputXml, hash), hash)
         ElseIf category = GeneratorCategory.RetrieveStoredProc Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     SpInputMetadata.RootData.LoadData(category, inputXml, hash), hash)
         ElseIf category = GeneratorCategory.RetrieveChildrenStoredProc Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     SpInputMetadata.RootData.LoadData(category, inputXml, hash), hash)
         ElseIf category = GeneratorCategory.RetrieveHierarchyStoredProc Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     SpInputMetadata.RootData.LoadData(category, inputXml, hash), hash)
         ElseIf category = GeneratorCategory.RetrieveSetStoredProc Then
            Return WrapperBase.SetXmlDocument(category, inputXml, _
                     SpInputMetadata.RootData.LoadData(category, inputXml, hash), hash)
         Else
            Throw New NotSupportedException(String.Format("This category type ({0}) is not supported", category))
         End If
         'Return WrapperBase.SetXmlDocument(inputXml, hash)
      End If
      Return Nothing
   End Function

   Private Function Generate( _
            ByVal name As String, _
            ByVal hash As Int32, _
            ByVal assemblyFileName As String, _
            ByVal templateName As String, _
            ByRef fileName As String) _
            As String _
            Implements IGenerator.Generate
      Return GetOutput(name, GetRootData(hash), assemblyFileName, templateName, fileName)
   End Function

   Private Function GetRootData(ByVal hash As Int32) As IRootData
      Return WrapperBase.GetRootData(hash)
   End Function

   'Private Shared Function GetCategoryString(ByVal category As GeneratorCategory) As String
   '   Dim ret As String = category.ToString()
   '   If ret.EqualsIgnoreCase("StoredProc") Then
   '      ret = "RunSP"
   '   End If
   '   Return ret
   'End Function

   'Private Class CacheSet
   '   Private mHashValue As Int32
   '   Public metadataCategory As String
   '   Public modifiedDate As DateTime
   '   Public xDocument As XDocument
   '   Public dataRoot As IRootData
   '   Public xFragment As XElement

   '   Public Sub New(ByVal name As String, _
   '                  ByVal xDocument As XDocument, _
   '                  ByVal dataRoot As IRootData, _
   '                  ByVal xFragment As XElement)
   '      Me.xDocument = xDocument
   '      Me.dataRoot = dataRoot
   '      Me.xFragment = xFragment
   '   End Sub

   '   Public Function BuildReturnElement() As XElement
   '      Return <s:<%= Name %>>
   '                <%= dataRoot.GetXList() %>
   '             </>
   '   End Function
   'End Class

   'Private mCache As New Dictionary(Of Int32, CacheSet)



   '#Region "Add-In Methods"

   '   Public Function SetXmlDocument( _
   '            ByVal inputXml As String) _
   '            As ISetupReturn _
   '            Implements ILinqGenerator.SetXmlDocument

   '      If String.IsNullOrEmpty(inputXml) Then
   '         Return Nothing
   '      End If
   '      Dim cacheSet As CacheSet = Nothing
   '      Dim hash = inputXml.GetHashCode()
   '      If mCache.TryGetValue(hash, cacheSet) Then
   '         Return New SetupReturn(hash, cacheSet.BuildReturnElement.ToString())
   '      End If
   '      Dim xDoc = XDocument.Parse(inputXml)
   '      cacheSet = New CacheSet(hash, xDoc, _
   '                              GenInputMetadata.RootData.LoadData(xDoc), _
   '                              SpInputMetadata.RootData.LoadData(xDoc), _
   '                              Nothing, Nothing)

   '      Console.WriteLine("Return Xml: " & (DateTime.Now.Ticks \ 1000).ToString)
   '      Return New SetupReturn(hash, cacheSet.BuildReturnElement().ToString())
   '   End Function

   'Dim ret = <s:Root>
   '             <s:Objects>
   '                <%= From obj In XDocument...<orm:Object> _
   '                   Select <s:Object <%= obj.Attributes %>/> %>
   '             </s:Objects>
   '             <s:Apis>
   '                <%= From api In XDocument...<orm:Api> _
   '                   Select <s:Api <%= api.Attributes %>/> %>
   '             </s:Apis>
   '             <s:Tables>
   '                <%= From table In XDocument...<orm:Table> _
   '                   Select <s:Table <%= table.Attributes %>/> %>
   '             </s:Tables>
   '             <s:StoredProcs>
   '                <%= From sp In XDocument...<orm:RunSP> _
   '                   Where sp.@Task.EqualsIgnoreCase("Create") _
   '                   Select <s:CreateStoredProc <%= sp.Attributes() %>/> %>
   '                <%= From sp In XDocument...<orm:RunSP> _
   '                   Where sp.@Task.EqualsIgnoreCase("Update") _
   '                   Select <s:UpdateStoredProc <%= sp.Attributes() %>/> %>
   '                <%= From sp In XDocument...<orm:RunSP> _
   '                   Where sp.@Task.EqualsIgnoreCase("Delete") _
   '                   Select <s:DeleteStoredProc <%= sp.Attributes() %>/> %>
   '                <%= From sp In XDocument...<orm:RunSP> _
   '                   Where sp.@Task.EqualsIgnoreCase("Retrieve") _
   '                   Select <s:RetrieveStoredProc <%= sp.Attributes() %>/> %>
   '                <%= From sp In XDocument...<orm:RunSP> _
   '                   Where sp.@Task.EqualsIgnoreCase("RetrieveChild") _
   '                   Select <s:RetrieveChildrenStoredProc <%= sp.Attributes() %>/> %>
   '                <%= From sp In XDocument...<orm:RunSP> _
   '                   Where sp.@Task.EqualsIgnoreCase("RetrieveHierarchy") _
   '                   Select <s:RetrieveHierarchyStoredProc <%= sp.Attributes() %>/> %>
   '                <%= From sp In XDocument...<orm:RunSP> _
   '                   Where sp.@Task.EqualsIgnoreCase("SetSelect") _
   '                   Select <s:RetrieveSetProc <%= sp.Attributes() %>/> %>
   '             </s:StoredProcs>
   '          </s:Root>.ToString()

   'Public Sub ClearXmlDocument() _
   '   Implements LinqGenerator.ILinqGenerator.ClearXmlDocument
   '   'xDocument = Nothing
   'End Sub

   'Public Function GetFileName( _
   '         ByVal name As String, _
   '         ByVal category As GeneratorCategory, _
   '         ByVal assemblyFileName As String, _
   '         ByVal templateName As String) _
   '         As String Implements _
   '         LinqGenerator.ILinqGenerator.GetFileName
   '   Dim template = GetTemplate(assemblyFileName, templateName)
   '   Return GetFileName(name, GetCategoryString(category), template)
   'End Function

   'Public Function Generate( _
   '         ByVal name As String, _
   '         ByVal category As GeneratorCategory, _
   '         ByVal assemblyFileName As String, _
   '         ByVal templateName As String, _
   '         ByVal token As Int32) _
   '         As IGenerateReturn _
   '         Implements ILinqGenerator.Generate
   '   Return GetReturn(name, category, 0, assemblyFileName, templateName)
   'End Function

   'Public Function GetOutput( _
   '         ByVal name As String, _
   '         ByVal category As GeneratorCategory, _
   '         ByVal assemblyFileName As String, _
   '         ByVal templateName As String) _
   '         As String _
   '         Implements ILinqGenerator.GetOutput
   '   Return GetOutput(name, GetCategoryString(category), assemblyFileName, templateName)
   'End Function

   'Public Function Generate( _
   '         ByVal name As String, _
   '         ByVal categoryString As String, _
   '         ByVal assemblyFileName As String, _
   '         ByVal templateName As String) _
   '         As IGenerateReturn _
   '         Implements ILinqGenerator.Generate
   '   'Console.WriteLine("Loaded Secondary app domain")
   '   'Dim element = (From x In xDocument...<Api> Where x.@Name = name).FirstOrDefault
   '   ' The zero is temporary
   '   Dim category = CType(System.Enum.Parse(GetType(GeneratorCategory), categoryString), GeneratorCategory)
   '   Return GetReturn(name, category, 0, assemblyFileName, templateName)
   'End Function

   'Public Function GetOutput( _
   '         ByVal name As String, _
   '         ByVal category As String, _
   '         ByVal assemblyFileName As String, _
   '         ByVal templateName As String) _
   '         As String _
   '         Implements ILinqGenerator.GetOutput
   '   'Console.WriteLine("Loaded Secondary app domain")
   '   'Dim element = (From x In xDocument...<orm:RunSP> Where x.@Name = name).FirstOrDefault
   '   Return GetTemplateOutput(GetElement(name, category), assemblyFileName, templateName)
   'End Function


   '#End Region

   '#Region "Private methods and properties"
   'Private Function GetElement( _
   '         ByVal name As String, _
   '         ByVal category As String) _
   '         As XElement
   '   Dim elementName = category
   '   If category.EndsWithIgnoreCase("StoredProc") Then
   '      elementName = "RunSP"
   '   End If
   '   ' TODO: THis must be moved across teh metadata boundary as this class should have no dependency on file structure
   '   Return (From x In xDocument.Descendants(GetXmlNamespace(orm) + elementName) _
   '                  Where x.@Name = name).FirstOrDefault
   'End Function

   'Private Function GetFileName( _
   '         ByRef name As String, _
   '         ByVal category As String, _
   '         ByVal template As ITemplate) _
   '         As String
   '   Dim element = GetElement(name, category)
   '   Return GetFileName(element, template)
   'End Function

   'Private Function GetFileName( _
   '         ByRef element As XElement, _
   '         ByVal template As ITemplate) _
   '         As String
   '   Return template.GetFileName(element)
   'End Function

   'Private Function GetTemplateOutput( _
   '        ByVal element As XElement, _
   '        ByVal assemblyFileName As String, _
   '        ByVal templateName As String, _
   '        ByRef fileName As String) _
   '        As String
   '   If element IsNot Nothing Then
   '      Dim template = GetTemplate(assemblyFileName, templateName)
   '      Return GetTemplateOutput(element, template, fileName)
   '   End If
   '   Return Nothing
   'End Function


   '#End Region


End Class